define([
  'jquery',
  'underscore',
  'backbone',
  'common/log/log'
], function ($, _, Backbone, Logger) {
  var logger = Logger.get('backbone-model-view');
  var Todo = Backbone.Model.extend({});
  var todo1 = new Todo();
  logger.info(JSON.stringify(todo1));

  var todo2 = new Todo({
    title: 'console title',
    completed: false
  });

  logger.info(JSON.stringify(todo2));

  // initialize

  var TodoEnhance = Backbone.Model.extend({
    defaults: function () {
      return {
        title: '',
        completed: false
      };
    },
    initialize: function () {
      logger.info(' this model has been initialized');
    }
  });


  var todo3 = new TodoEnhance({
    title: 'TodoEnhance'
  });


  todo2.listenTo(todo3, 'change:title', function (value) {
    logger.log('todo2 listen todo3 title changed');
  });

  todo3.on('change:title', function (value) {
    logger.log('todo3 listened own change event');
  });
  logger.log(todo3.get('title'));
  todo3.set('title', 'dodo changed');

  // 直接访问 model的attributes，这里时保存model属性的地方
  // 直接访问不会出发change事件
  logger.log(todo3.attributes);

  // 监听模型的变化
  var TodoWithListener = Backbone.Model.extend({
    defaults: function (param) {
      return {
        completed: false,
        title: ''
      };
    },
    initialize: function (attributes, options) {
      logger.log('initialized Todo');
      this.on('change', function (model) {
        logger.log('value changed to ' + JSON.stringify(model.changedAttributes()));
      });
    }
  });

  var todo4 = new TodoWithListener();
  todo4.set('title', 'TodoWithListener');
  todo4.set('title', 'doWithListener');

  var TodoValidate = Backbone.Model.extend({
    defaults: function () {
      return {
        completed: false
      };
    },
    validate: function (attributes) {
      if (attributes.title === undefined) {
        return ' remember to set a title for you todo'
      }
    },
    initialize: function (attributes, options) {
      this.on('invalid', function (model, err, options) {
        logger.log(err);
        logger.log(this.validationError);
        logger.log(options.validationError);
        logger.log('err === this.validationError === optins.validationError: ' + (err === this.validationError));
      });
    }
  });

  // 监听validate方法
  var validateTodo = new TodoValidate();
  validateTodo.set('completed', true, { validate: true });


  // *** views ***

  var TodoView = Backbone.View.extend({
    initialize: function (attributes, optios) {
      this.model.on('change', _.bind(this.render, this));
    },
    el: '#todoApp',
    todoTpl: _.template('<li><p class="text-info"> <%= text %></p><li>'),
    events: {
      'dbclick label': 'edit',
      'keypress .edit': 'updateOnEnter',
      'blue .edit': 'close'
    },
    render: function (param) {
      this.$el.html(this.todoTpl(this.model.toJSON()));
      this.input = this.$('.edit');
      return this;
    },
    close: $.noop,
    updateOnEnter: $.noop,
    edit: $.noop
  });

  var ViewModel = Backbone.Model.extend({
    defaults: {
      text: ''
    }
  });
  var viewModel1 = new ViewModel({
    text: 1
  })
  var view1 = new TodoView({
    model: viewModel1
  });
  // logger.info(view1.el);
  viewModel1.set('text', 0);

  // *** Collection ***
  var TodoCollection = Backbone.Collection.extend({
    model: ViewModel
  });

  var todos = new TodoCollection();
  todos.add(viewModel1);

  logger.log('todos.size = ' + todos.size());

  todos.add({ text: '2', id: 9 });
  logger.log('todos.size = ' + todos.size());
  viewModel1.set('text', 2);

  // remove model from collection
  logger.log('print viewModel1 JSON, find viewModel1 =' + JSON.stringify(todos.get(viewModel1.cid)));
  todos.remove(viewModel1);
  logger.log('after remove viewModel1 from todos, todos.size = ' + todos.size());

  // 集合绑定元素
  todos.on({
    'change:title': function (model) {
      logger.log('title changed to ' + model.get('title'));
    }
  });
  // 改变集合中模型的属性值
  todos.get(9).set('title', 'title-9');

  // events once
  var TodoCounter = {
    counterA: 0,
    counterB: 0
  };

  _.extend(TodoCounter, Backbone.Events);

  var incrA = function () {
    TodoCounter.counterA += 1;
    TodoCounter.trigger('event');
  };

  var incrB = function () {
    TodoCounter.counterB += 1;
  }

  TodoCounter.once('event', incrA);
  TodoCounter.once('event', incrB);

  TodoCounter.trigger('event');

  logger.log('counterA: ' + TodoCounter.counterA + ' and counterB: ' + TodoCounter.counterB);


  // collection reset and refresh
  // 一次添加多个模型
  todos.set([{
    title: 'json',
    completed: true
  }, {
    title: 'reset2',
    completed: false
  }, {
    title: 'reset1',
    completed: false
  }]);

  logger.log('todos使用set添加多个模型之后的size = ' + todos.size());

  // reset不会触发 add 或者 remove事件，触发reset事件，通过访问options.previousModels能够访问reset之前的模型
  todos.on({
    reset: function (todos, options) {
      logger.log('after reset, models = ' + JSON.stringify(todos));
      logger.log('before reset , models = ' + JSON.stringify(options.previousModels));
    }
  });

  // todos.reset();

  todos.forEach(function (model) {
    logger.log('forEach todos , current model title is ' + model.get('title'));
  });

  var sortedTodos = todos.sortBy(function (model) {
    return model.get('title').toLowerCase();
  });


  sortedTodos.forEach(function (model) {
    logger.log('todos after sortBy title , current model title is ' + model.get('title'));
  });

  var todoTitles = todos.map(function (todo) {
    return todo.get('title');
  });
  todoTitles.forEach(function (title) {
    logger.log(title);
  });

  // chain api
  var collection = new Backbone.Collection([{
    name: 'tim',
    age: 35
  }, {
    name: 'ida',
    age: 20
  }, {
    name: 'rob',
    age: 55
  }]);

  var filteredNames = collection.chain()
    .filter(function (item) { return item.get('age') > 20 })
    .map(function (item) { return item.get('name'); }).value();

  logger.log('chain demo , filteredNames = ' + JSON.stringify(filteredNames));

  // RESTful持久化
  // Collections.fetch()

  // Collection.save()

  var TodoFromServer = Backbone.Model.extend({
    defaults: {
      title: '',
      completed: false
    }
  });

  var TodosFromServer = Backbone.Collection.extend({
    model: TodoFromServer,
    url: '/todos'
  });
  var todosFromServer = new TodosFromServer();

  // 从服务的初始化集合
  // http get
  todosFromServer.fetch();
  logger.log('todosFromServer error, not /todos service');

  var todoFromServer = new TodoFromServer({
    title: 'todosFromServer add model',
    completed: false
  });
  todosFromServer.add(todoFromServer);

  // 模型保存，发送http put
  // 调用validate方法；非法触发invaild事件
  todoFromServer.save(); // 储存到服务器

  // 集合创建单个数据模型，发送http post请求
  todosFromServer.create({
    title: 'todo created by backbone',
    completed: false
  });

  // 从服务器删除模型
  // Backbone.Model.destory
  // 新建的模型上会返回false，不会发送http请求
  // 发送http delete
  logger.log('print Backbone.Model.destroy return value = ' + todoFromServer.destroy());

  // Backbone.Collection.remove
  // 不发送http请求
  todosFromServer.remove(todoFromServer);

  // *** Events ***
  // Backbone作为全局的事件总线
  Backbone.on('dodo', function (data) {
    logger.log('dodo events from Backbone, arguments = ' + JSON.stringify(arguments));
  });

  // 特殊事件'all'
  Backbone.on('all', function () {
    logger.log('all event handler, arguments = ' + JSON.stringify(arguments));
  });

  Backbone.trigger('dodo', {
    comment: 'dodo events trigged by Backbone.'
  }, 'second arguments');

  // on, off, trigger
  // model.on('change, add, delete', function () {});
  // model.trigger('change, add, delete', {comment: 'trigger 多个事件'});
  // model.off('change, add, delete'); // 移除多个事件处理函数
  // model.off('change', handlerFucn); // 移除制定的事件处理函数

  // listenTo, stopListening
  // listenTo是语法糖，内部就是viewModel1.on('change:title', handler)
  todo1.listenTo(viewModel1, 'change:title', function (model) {
    logger.log('todo listenTo viewModel1 title changing');
  });

});
